package com.tangyuan.live.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangyuan.common.result.Result;
import com.tangyuan.common.result.ResultCodeEnum;
import com.tangyuan.common.util.DurationUtil;
import com.tangyuan.feignapis.user.IUserConcernFeignClient;
import com.tangyuan.feignapis.user.IUserFeignClient;
import com.tangyuan.live.entity.dto.LiveSaveDto;
import com.tangyuan.live.entity.enums.LiveManagementTypeEnum;
import com.tangyuan.live.entity.enums.LiveRoleEnum;
import com.tangyuan.live.entity.vo.*;
import com.tangyuan.live.entity.dto.LiveQueryDto;
import com.tangyuan.live.entity.enums.LiveRoomStatusEnum;
import com.tangyuan.live.service.*;
import com.tangyuan.live.mapper.LiveRoomMapper;
import com.tangyuan.live.util.IMUtil;
import com.tangyuan.live.util.LiveUtil;
import com.tangyuan.model.User;
import com.tangyuan.model.live.LiveRoom;
import com.tangyuan.vo.MyInfoMissionVo;
import com.tangyuan.vo.UserHeadImageVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class LiveRoomServiceImpl extends ServiceImpl<LiveRoomMapper, LiveRoom> implements LiveRoomService{

    @Autowired
    IUserFeignClient iUserFeignClient;
    @Autowired
    LiveManagementService liveManagementService;
    @Autowired
    IUserConcernFeignClient userConcernFeignClient;
    @Autowired
    IUserFeignClient userFeignClient;
    @Autowired
    LiveGiveGiftService liveGiveGiftService;
    @Autowired
    LiveViewRecordService liveViewRecordService;
    @Autowired
    LiveGroupService liveGroupService;
    @Autowired
    IMUtil imUtil;
    @Autowired
    LiveUtil liveUtil;

    /**
     * 用户查询直播列表
     * @param dto 查询条件
     * @return 直播中的直播列表
     */
    @Override
    public Page<LiveRoomListVo> getLiveRoomList(LiveQueryDto dto) {
        QueryWrapper<LiveRoom> wrapper = new QueryWrapper<>();
        wrapper.lambda().like(StrUtil.isNotEmpty(dto.getRoomName()),LiveRoom::getRoomName,dto.getRoomName());
        wrapper.lambda().eq(LiveRoom::getStatus, LiveRoomStatusEnum.UNDERWAY.status);
        Long count = baseMapper.selectCount(wrapper);
        if(count <= 0){
            return new Page<>();
        }
        Page<LiveRoomListVo> roomPage = baseMapper.getLiveRoomList(new Page<LiveRoom>(dto.getPageNum(), dto.getPageSize()), wrapper);
        roomPage.setTotal(count);
        List<LiveRoomListVo> records = roomPage.getRecords();
        if(CollectionUtils.isEmpty(records)){
            return roomPage.setRecords(new ArrayList<>());
        }
        List<Long> userIds = records.stream().map(LiveRoomListVo::getUserId).collect(Collectors.toList());
        Map<Long, User> byId = iUserFeignClient.getUserListById(userIds);
        for (LiveRoomListVo record : records) {
            User user = byId.get(record.getUserId());
            if(user == null){
                log.error("该用户不存在,userID:{}",record.getUserId());
                continue;
            }
            record.setUserName(user.getName());
            record.setHeadImage(user.getHeadImage());
        }
        return roomPage.setRecords(records);
    }

    /**
     * 我的直播记录
     * @param userId 用户ID
     * @param dto 查询条件
     * @return 我的直播
     */
    @Override
    public Page<MyLiveVo> getMyLiveList(Long userId, LiveQueryDto dto) {
        QueryWrapper<LiveRoom> wrapper = new QueryWrapper<>();
        wrapper.lambda().like(StrUtil.isNotEmpty(dto.getRoomName()),LiveRoom::getRoomName,dto.getRoomName());
        wrapper.lambda().eq(LiveRoom::getUserId,userId);
        Long count = baseMapper.selectCount(wrapper);
        if(count <= 0){
            return new Page<>();
        }
        wrapper.lambda().orderByDesc(LiveRoom::getStartTime);
        Page<MyLiveVo> list = baseMapper.getMyLiveList(new Page<LiveRoom>(dto.getPageNum(), dto.getPageSize()), wrapper);
        return list.setTotal(count);
    }

    @Override
    public Result<LiveRoomVo> createLiveRoom(Long userId, LiveSaveDto dto) {
        User user = iUserFeignClient.getUserById(userId);
        if(user == null){
            return Result.build(null,ResultCodeEnum.USER_NOT_EXIST);
        }
        if(user.getIsCreateIm() == null ||user.getIsCreateIm() == 1){
            return Result.build(null,ResultCodeEnum.NO_LIVE_PERMISSIONS);
        }
        List<MyLiveVo> list = this.getMyLiveList(userId, new LiveQueryDto()).getRecords();
        if(!CollectionUtils.isEmpty(list)){
            MyLiveVo liveVo = list.get(0);
            if(liveVo.getStatus().equals(LiveRoomStatusEnum.UNDERWAY.status)){
                return Result.ok(getLiveRoomVo(baseMapper.selectById(liveVo.getId()),true));
            }
        }

        LiveRoom room = new LiveRoom();
        room.setPushUrl(liveUtil.joinLivePushUrl(userId));
        room.setPlayUrl(liveUtil.joinLivePlayUrl(userId));
        //房间名和开始时间
        room.setUserId(userId);
        room.setRoomName(dto.getRoomName());
        room.setCoverImage(dto.getCoverImage());
        room.setStartTime(new Date());
        room.setStatus(LiveRoomStatusEnum.UNDERWAY.status);
        Result<String> result = liveGroupService.createGroup(room);
        if(!result.isOk()){
            return Result.build(null,result.getCode(),result.getMessage());
        }
        room.setGroupId(result.getData());
        baseMapper.insert(room);
        return Result.ok(getLiveRoomVo(room,true));
    }


    @Override
    public Result<EndLiveVo> endLive(Long userId, Long roomId) {
        LiveRoom live = baseMapper.selectById(roomId);
        if(live == null){
            return Result.build(null,ResultCodeEnum.NO_DATA);
        }
        if(!live.getUserId().equals(userId)){
            return Result.build(null,ResultCodeEnum.NO_SEARCH_DATA);
        }
        if(live.getStatus().equals(LiveRoomStatusEnum.FINISHED.status)){
            return Result.build(null,ResultCodeEnum.LIVE_FINISHED);
        }
        //新增粉丝数
        Long concernNum = userConcernFeignClient.getLiveConcernNum(userId, 3, roomId);
        //直播时长
        String durationStr = DurationUtil.calculateDuration(new Date().getTime(), live.getStartTime().getTime());
        //直播收入
        BigDecimal income = liveGiveGiftService.getLiveIncome(roomId);
        //观看总人数
        Long viewNumber = liveViewRecordService.getMaxViewNumber(roomId);
        //打赏前三
        List<GiftRankingVo> rankingVoList = liveGiveGiftService.giftRanking(roomId);

        //保存直播数据
        baseMapper.update(null,new LambdaUpdateWrapper<LiveRoom>()
                .set(LiveRoom::getEndTime,new Date())
                .set(LiveRoom::getLiveDuration,durationStr)
                .set(LiveRoom::getLiveIncome,income)
                .set(LiveRoom::getViewNumber,viewNumber)
                .set(LiveRoom::getNewFollowersNum,concernNum)
                .set(LiveRoom::getStatus,LiveRoomStatusEnum.FINISHED.status)
                .eq(LiveRoom::getId,roomId));
        User user = iUserFeignClient.getUserById(userId);
        EndLiveVo build = EndLiveVo.builder()
                .liveDuration(durationStr)
                .liveIncome(income)
                .viewNumber(viewNumber)
                .newFollowersNum(concernNum)
                .giftRankingVos(rankingVoList)
                .userId(user.getId())
                .userName(user.getName())
                .userHeadUrl(user.getHeadImage())
                .status(LiveRoomStatusEnum.FINISHED.status)
                .build();
        liveGroupService.destroyGroup(live.getGroupId());
        return Result.ok(build);
    }

    @Override
    public Result<LiveRoom> getLiveRoomById(Long roomId) {
        if(roomId == null || roomId == 0){
            return Result.build(null,ResultCodeEnum.NO_DATA);
        }
        LiveRoom room = baseMapper.selectById(roomId);
        if(room == null){
            return Result.build(null,ResultCodeEnum.NO_SEARCH_DATA);
        }
        if(!room.getStatus().equals(LiveRoomStatusEnum.UNDERWAY.status)){
            return Result.build(null,ResultCodeEnum.LIVE_FINISHED);
        }
        return Result.ok(room);
    }

    @Override
    public LiveRoomVo getLiveRoomVo(LiveRoom room,boolean flag){
        LiveRoomVo roomVo = new LiveRoomVo();
        BeanUtils.copyProperties(room,roomVo);
        User byId = iUserFeignClient.getUserById(room.getUserId());
        //主播信息
        UserHeadImageVo headImageVo = new UserHeadImageVo();
        headImageVo.setHeadImage(byId.getHeadImage());
        headImageVo.setUserName(byId.getName());
        headImageVo.setUserId(byId.getId());
        roomVo.setAnchor(headImageVo);
        //如果是创建直播直接返回
        if(flag){
            roomVo.setMemberCount(0L);
            roomVo.setThumpCount(0L);
            roomVo.setTopUsers(new ArrayList<>());
            return roomVo;
        }
        //在线人数
        roomVo.setMemberCount(imUtil.getOnLineNumber(room.getGroupId()));
        roomVo.setTopUsers(liveGiveGiftService.giftRanking(room.getId()));
        return roomVo;
    }

    @Override
    public Result<ResultCodeEnum> createIMUser(User user) {
        if(user == null){
            return Result.fail(ResultCodeEnum.NO_SEARCH_DATA);
        }
        if(user.getIsCreateIm() == 0){
            return Result.ok();
        }
        String utilIMUser = imUtil.createIMUser(user);
        if(StrUtil.isEmpty(utilIMUser)){
            return Result.fail(ResultCodeEnum.FAIL);
        }
        return Result.ok();
    }

    @Override
    public String generateUserSig(Long userId) {
        return imUtil.generateUserSig(userId.toString());
    }

    @Override
    public Result<LiveUserMsgVo> getLiveUserMsg(Long userId, Long liveUserId,Long liveRoomId) {
        Result<LiveRoom> result = getLiveRoomById(liveRoomId);
        if(!result.isOk()){
            return Result.build(null,result.getCode(),result.getMessage());
        }
        LiveRoom room = result.getData();
        MyInfoMissionVo infoMission = userFeignClient.getMyInfoMission(liveUserId).getData();
        if(infoMission == null){
            return Result.build(null,ResultCodeEnum.USER_NOT_EXIST);
        }
        LiveUserMsgVo userMsgVo = new LiveUserMsgVo();
        BeanUtils.copyProperties(infoMission,userMsgVo);
        userMsgVo.setConsumePrice(liveGiveGiftService.getUserConsumePrice(liveUserId,liveRoomId));
        userMsgVo.setIsConcern(userConcernFeignClient.isConcern(userId,liveUserId).getData());
        userMsgVo.setIsShutUp(liveManagementService.isShiftOutOrShutUp(liveUserId,liveRoomId, LiveManagementTypeEnum.SHUT_UP.type));
        userMsgVo.setRole(room.getUserId().equals(liveUserId) ? LiveRoleEnum.ANCHOR.role:LiveRoleEnum.AUDIENCE.role);
        return Result.ok(userMsgVo);
    }

    public List<LiveRoom> getNoCloseLiveByUserIds(List<Long> userId,Integer status){
        if(CollectionUtils.isEmpty(userId)){
            return new ArrayList<>();
        }
        LambdaQueryWrapper<LiveRoom> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(LiveRoom::getUserId,userId);
        queryWrapper.in(status != null,LiveRoom::getStatus,status);
        return baseMapper.selectList(queryWrapper);
    }
}




